package  
{
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	import org.flixel.*;
	import org.flixel.plugin.photonstorm.*;
	import org.flixel.plugin.photonstorm.BaseTypes.Bullet;
	
	/**
	 * ...
	 * @author le-ray_y
	 */
	public class Game extends FlxState 
	{
		//************************************************************************
		//** 							VARIABLES								**
		//************************************************************************
		
		// Background
		[Embed(source = '../../Assets/bg.jpg')]
		private var _backGroundClass:Class;
		private var _backGround:FlxSprite;
		
		// Timer Text
		public var _timerText:FlxText;
		
		// Timer
		private var _timer:Timer;
		
		// Oil
		private var _oil:Oil;
		
		// Poison
		private var _poison:Poison;
		
		// Weapon
		private var _weapon:FlxWeapon;
		[Embed(source = '../../Assets/carotte.png')]
		private var _bulletGraph:Class;
		private var _enemyLaunched:Boolean = false;
		
		// MouseAttack Graph
		[Embed(source = '../../Assets/btn_clic.png')]
		private var _mouseAttackClass:Class;
		public var _mouseAttackBtn:CustomButton;
		
		// Poison Graph
		[Embed(source = '../../Assets/btn_poison.png')]
		private var _poisonClass:Class;
		public var _poisonBtn:CustomButton;
		
		// Oil Graph
		[Embed(source = '../../Assets/btn_oil.png')]
		private var _oilClass:Class;
		public var _oilBtn:CustomButton;
		
		// Bow Graph
		[Embed(source = '../../Assets/btn_archer.png')]
		private var _bowClass:Class;
		public var _bowBtn:CustomButton;
		
		// gameOver ?
		private var isGameOver:Boolean = false;
		
		// reticle ?
		private var hasReticle:Boolean = false;
		
		
		//************************************************************************
		//** 							FUNCTIONS								**
		//************************************************************************
		
		// CREATE
		override public function create():void
		{
			// Framerate
			FlxG.framerate = 50;
			FlxG.flashFramerate = 50;
			
			//	Enable the plugin - you only need do this once in your State (unless you destroy the plugin)
			if (FlxG.getPlugin(FlxMouseControl) == null)
			{
				FlxG.addPlugin(new FlxMouseControl);
			}
			
			// Background
			_backGround = new FlxSprite(0, 0, _backGroundClass);
			this.add(_backGround);
			
			// Tower
			Global.tower = new Tower(800 - 219, 96, 200);
			this.add(Global.tower);
			
			// Enemy Array & Creation
			Global.enemies = new FlxGroup();
			this.add(Global.enemies);
			
			// Score Text
			_timerText = new FlxText(79, 11, 178, "0");
			_timerText.alignment = "center";
			_timerText.size = 20;
			this.add(_timerText);
			
			// Oil
			_oil = new Oil(538, 296);
			this.add(_oil);
			
			// Goal Weapon
			_weapon = new FlxWeapon("bow", Global.tower);
			_weapon.makeImageBullet(500, _bulletGraph, 8, 8);
			_weapon.setBulletOffset(0, 225);
			_weapon.setBulletSpeed(250);
			_weapon.setBulletGravity(0, 400);
			this.add(_weapon.group);
			
			// Poison
			_poison = new Poison(-100, -100);
			this.add(_poison);
			
			gameTimer();
			
			//Make enemies
			makeEnemies(100);
			
			// MouseAttack
			_mouseAttackBtn = new CustomButton(271, 6, 1, onMouseAttackClick);
			_mouseAttackBtn.disableMouseClicks();
			_mouseAttackBtn.loadGraphic(_mouseAttackClass, false, false, 60, 60);
			this.add(_mouseAttackBtn);
			
			// PoisonAttack
			_poisonBtn = new CustomButton(337, 6, 10, onPoisonClick);
			_poisonBtn.loadGraphic(_poisonClass, false, false, 60, 60);
			this.add(_poisonBtn);
			
			// OilAttack
			_oilBtn = new CustomButton(403, 6, 10, onOilClick);
			_oilBtn.loadGraphic(_oilClass, false, false, 60, 60);
			this.add(_oilBtn);
			
			// BowAttack
			_bowBtn = new CustomButton(469, 6, 20, onBowClick);
			_bowBtn.loadGraphic(_bowClass, false, false, 60, 60);
			this.add(_bowBtn);
			
			// Enemy Timer
			_timer = new Timer(500, 0);
			_timer.start()
			_timer.addEventListener(TimerEvent.TIMER, timerlaunchEnemy);
		}
		
		private function timerlaunchEnemy(e:TimerEvent):void 
		{
			launchEnemy();
		}
			
		private function onMouseAttackClick(obj1:CustomButton, obj2:Number, obj3:Number):void 
		{
			trace ("MouseAttack");
			obj1.exists = false;
			obj1.startCooldown();
		}
		
		private function onPoisonClick(obj1:CustomButton, obj2:Number, obj3:Number):void 
		{
			trace ("Poison");
			obj1.exists = false;
			obj1.startCooldown();
			
			hasReticle = true;
		}
		
		private function onOilClick(obj1:CustomButton, obj2:Number, obj3:Number):void 
		{
			trace ("Oil");
			fireOil();
			obj1.exists = false;
			obj1.startCooldown();
		}
		
		private function onBowClick(obj1:CustomButton, obj2:Number, obj3:Number):void 
		{
			trace ("Bow");
			fireArrows(20);
			obj1.exists = false;
			obj1.startCooldown();
		}
		
		override public function update():void
		{
			super.update();
			
			if (hasReticle)
			{
				_poison.play("reticle");
				_poison.x = FlxG.mouse.x;
				_poison.y = FlxG.mouse.y;
				
				if (FlxG.mouse.justPressed())
				{
					hasReticle = false;
					_poison.play("poison");
				}
			}
			
			// Launch Enemy
			if (FlxG.keys.justPressed("SPACE"))
			{
				launchEnemy();
			}
			
			/*// Oil Spill
			if (FlxG.keys.justPressed("E"))
			{
				fireOil();
			}
			
			// Fire Bow
			if (FlxG.keys.justPressed("R"))
			{
				fireArrows(30);
			}*/
			
			/*******************
			** Collision handler
			********************/
			
			// Arrows and enemies
			FlxG.overlap(_weapon.group, Global.enemies, onArrowCollide);
			
			if (Global.enemies.getFirstAlive() != null)
			{
				for (var i:Number = 0; i < Global.enemies.length; i++)
				{
					if (FlxCollision.pixelPerfectCheck(Global.enemies.members[i], Global.tower))
					{
						onEnemyTowerCollide(Global.enemies.members[i], Global.tower);
					}
					
					if (FlxCollision.pixelPerfectCheck(Global.enemies.members[i], _oil))
					{
						onEnemySpillCollide(Global.enemies.members[i], _oil);
					}
					
					if (!hasReticle)
						if (FlxCollision.pixelPerfectCheck(Global.enemies.members[i], _poison))
						{
							onEnemySpillCollide(Global.enemies.members[i], _oil);
						}
				}
			}
			
			// Game Over
	
			if (Global.tower.health <= 0)
			{
				gameOver();
				FlxG.switchState(new GameOver());
			}
		}
		
		private function gameOver():void 
		{
			isGameOver = true;
			_timer.stop()
			_timer.removeEventListener(TimerEvent.TIMER, timerlaunchEnemy);
			_timer.removeEventListener(TimerEvent.TIMER, onGameTimer);
		}
		
		private function onArrowCollide(obj1:Bullet, obj2:Enemy):void 
		{
			obj1.kill();
			obj2.alive = false;
		}
		
		private function onEnemyTowerCollide(enemy:Enemy, tower:Tower):void 
		{
			if (enemy.alive)
			{
				enemy.velocity.x = enemy.velocity.y = 0;
				enemy.stopFollowingPath();
				enemy.play("attack");
			}
		}
		
		private function onEnemySpillCollide(enemy:Enemy, oil:Oil):void 
		{
			enemy.alive = false;
		}
		
		private function fireOil():void 
		{
			_oil.play("spill");
		}
		
		private function fireArrows(value:Number):void 
		{
			_timer = new Timer(50, value);
			_timer.start();
			_timer.addEventListener(TimerEvent.TIMER, onLaunchArrow);
		}
		
		private function onLaunchArrow(e:TimerEvent):void 
		{
			_weapon.setBulletSpeed(250 + 200 * Math.random());
			_weapon.fireFromAngle(-135 - 10 * Math.random());
		}
		
		private function gameTimer():void 
		{
			_timer = new Timer(1000, 0);
			_timer.start();
			_timer.addEventListener(TimerEvent.TIMER, onGameTimer);
		}
		
		private function onGameTimer(e:TimerEvent):void 
		{
			if (!isGameOver)
			{
				var tmp:Number;
				tmp = Number(_timerText.text);
				_timerText.text = String(tmp + 1);
			}
		}
		
		// Creates all the enemies
		private function makeEnemies(value:Number):void 
		{
			for (var i:Number = 0; i < value; i++)
			{
				var enemy:Enemy = new Enemy(-50, 515 - 37 / 2, 1, 40, onEnemyClick);
				Global.enemies.add(enemy);
			}
			
			trace ("---- Enemy creation: DONE ----  " + Global.enemies.length); 
		}
		
		public function onEnemyClick(obj1:Enemy, obj2:Number, obj3:Number):void 
		{
			if (_mouseAttackBtn.exists)
			{
				_mouseAttackBtn.exists = false;
				_mouseAttackBtn.startCooldown();
				obj1.alive = false;
			}
		}
		
		// Launch an available enemy
		public function launchEnemy():void 
		{
			var currentEnemy:Enemy;
			
			currentEnemy = getFreeEnemy();
			
			if (currentEnemy == null)
			{
				trace ("No enemies available");
			}
			else
			{
				currentEnemy.resetEnemy(-50, 515 - 37 / 2 + Math.random() * 25, 1, 50);
			}
		}
		
		// Returns an available enemy
		public function getFreeEnemy():Enemy 
		{
			var result:Enemy = null;
			
			if (Global.enemies == null || Global.enemies.length == 0)
			{
				throw new Error("Game.as cannot launch an enemy until one has been created via a call to makeEnemies");
				return null;
			}
			
			for each (var enemy:Enemy in Global.enemies.members)
			{
				if (enemy.exists == false)
				{
					result = enemy;
					break;
				}
			}
			return result;
		}
	}
}